#include "cgzCLua.h"
#include "cgzCTcpWC.h"
#include "cgzCThreadPool.h"

bool cgzCLua::runwc(const cgzITask *iTask, cgzCLoopC *pnode)
{
    auto etype = pnode->getEType();
    switch (etype)
    {
    case TCPC_ACPT: // 连接成功
    {
        ocall(iTask->m_tref, "accept", {});
    }
    break;
    case TCPC_RECV: // 接收数据
    {
        auto *recvwc = static_cast<cgzCRecvWC *>(pnode);
        switch (recvwc->rt)
        {
        case WEBSOCKET_SEND_PING:
        {
            ocall(iTask->m_tref, "ping", {});
        }
        break;
        case WEBSOCKET_SEND_PONG:
        {
            ocall(iTask->m_tref, "pong", {});
        }
        break;
        case WEBSOCKET_SEND_TEXT:
        {
            ocall(iTask->m_tref, "recvt", {{recvwc->m_data, recvwc->m_len}});
        }
        break;
        case WEBSOCKET_SEND_BINARY:
        {
            auto &header = *(cgzHeader *)(recvwc->m_data);
            auto data = (const char *)(recvwc->m_data + sizeof(cgzHeader));
            ocall(iTask->m_tref, "recvb", {
                header.mid, 
                {data, header.len}, 
                (long)header.cid
            });
        }
        break;
        default:
        {
            cgz_this_error("task tcpWC :{} recvWC:{} not support", iTask->getName(), recvwc->rt);
        }
        }
    }
    break;
    case TCPC_DISC: // 断开连接
    {
        ocall(iTask->m_tref, "disc", {});
    }
    break;
    default:
    {
        cgz_this_error("task tcpWC :{} etype:{} not support", iTask->getName(), (int)etype);
    }
    }
    return true;
}

static int wc_link(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    const char *ip = lua_tostring(L, 2);
    int port = lua_tointeger(L, 3);
    int tref = luaL_ref(L, LUA_REGISTRYINDEX);
    void *node = malloc(sizeof(cgzCTcpWC));
    int cid = that->getId();
    auto ctcp = new (node) cgzCTcpWC(that->m_pool, name, ip, port, cid);
    ctcp->m_tref = tref;
    ctcp->tcpinit();
    return 0;
}

static int wc_text(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    size_t len = 0;
    const char *pck = lua_tolstring(L, 2, &len);
    void *node = malloc(sizeof(cgzCSendWC));
    auto psend = new (node) cgzCSendWC(pck, len, WEBSOCKET_SEND_TEXT);
    that->regTask(name, psend);
    return 0;
}

static int wc_send(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    const int mid = lua_tointeger(L, 2);
    size_t len = 0;
    const char *pck = lua_tolstring(L, 3, &len);
    int all = len + sizeof(cgzHeader);
    // 添加消息头
    auto buffer = (char *)malloc(all);
    auto &header = *(cgzHeader *)(buffer);
    header.mid = mid;
    header.len = len;
    header.all = all;
    header.cid = luaL_checkinteger(L, 4);
    // 拷贝内容
    memcpy(buffer + sizeof(cgzHeader), pck, len);
    void *node = malloc(sizeof(cgzCSendWC));
    auto psend = new (node) cgzCSendWC(buffer, all, WEBSOCKET_SEND_BINARY);
    that->regTask(name, psend);
    free(buffer);
    return 0;
}

int cgzCLua::luaopen_tcpWC(lua_State *L)
{
    static const luaL_Reg otherlib[] = {
        {"link", wc_link},
        {"text", wc_text},
        {"send", wc_send},
        {NULL, NULL}};

    luaL_newlib(L, otherlib);
    return 1;
}